package com.it.schoolbookshop_back.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.schoolbookshop_back.service.NotificationService;
import com.it.schoolbookshop_back.service.impl.NotificationServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket通知处理器
 * 用于处理实时通知，包括消息通知、收藏通知和交易通知
 */
@Component
public class NotificationWebSocketHandler extends TextWebSocketHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(NotificationWebSocketHandler.class);
    
    // 存储所有活跃的WebSocket会话，键为用户ID
    private static final Map<Integer, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private void setNotificationServiceSessions() {
        // 注入用户会话到NotificationService
        if (notificationService instanceof NotificationServiceImpl) {
            ((NotificationServiceImpl) notificationService).setUserSessions(userSessions);
            logger.info("已更新通知服务中的用户会话信息，当前活跃会话数: {}", userSessions.size());
        }
    }
    
    /**
     * 处理收到的WebSocket消息
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        logger.info("NotificationWebSocketHandler - 收到消息: {}", payload);
        
        try {
            // 检查是否是心跳包
            if (payload.contains("\"type\"") && payload.contains("\"HEARTBEAT\"")) {
                logger.debug("收到心跳包: {}", payload);
                // 心跳包，发送回应
                Map<String, Object> heartbeatResponse = new HashMap<>();
                heartbeatResponse.put("type", "HEARTBEAT");
                heartbeatResponse.put("timestamp", System.currentTimeMillis());
                String responseText = objectMapper.writeValueAsString(heartbeatResponse);
                session.sendMessage(new TextMessage(responseText));
                logger.debug("已发送心跳响应: {}", responseText);
                return;
            }
            
            // 检查是否是身份标识消息
            if (payload.contains("\"type\"") && payload.contains("\"IDENTITY\"")) {
                logger.info("收到身份标识消息: {}", payload);
                // 解析消息中的用户ID
                Map<String, Object> identityMsg = objectMapper.readValue(payload, Map.class);
                Object userIdObj = identityMsg.get("userId");
                Integer userId = null;
                
                if (userIdObj instanceof Integer) {
                    userId = (Integer) userIdObj;
                } else if (userIdObj instanceof String) {
                    try {
                        userId = Integer.parseInt((String) userIdObj);
                    } catch (NumberFormatException e) {
                        logger.error("无法解析用户ID: {}", userIdObj);
                    }
                } else if (userIdObj instanceof Number) {
                    userId = ((Number) userIdObj).intValue();
                }
                
                if (userId != null) {
                    // 将用户会话存储起来
                    userSessions.put(userId, session);
                    logger.info("通过IDENTITY消息更新用户(ID:{})的会话", userId);
                    
                    // 更新通知服务中的用户会话信息
                    setNotificationServiceSessions();
                    
                    // 发送确认消息
                    Map<String, Object> confirmMsg = new HashMap<>();
                    confirmMsg.put("type", "CONFIRMATION");
                    confirmMsg.put("message", "身份信息已接收");
                    confirmMsg.put("timestamp", System.currentTimeMillis());
                    
                    session.sendMessage(new TextMessage(objectMapper.writeValueAsString(confirmMsg)));
                    logger.info("已发送身份确认消息给用户ID: {}", userId);
                } else {
                    logger.error("身份标识消息中的用户ID解析失败");
                    sendErrorMessage(session, "身份信息不完整");
                }
                return;
            }
            
            // 解析用户ID
            Integer userId = getUserIdFromSession(session);
            if (userId == null) {
                logger.error("无法从会话中获取用户ID");
                sendErrorMessage(session, "无法获取用户ID");
                return;
            }
            
            // 此处可以添加更多消息处理逻辑
            // 对于通知WebSocket，前端主要是接收消息，很少发送消息
            
            // 默认情况下，发送确认消息
            Map<String, Object> response = new HashMap<>();
            response.put("type", "CONFIRMATION");
            response.put("message", "消息已收到");
            response.put("timestamp", System.currentTimeMillis());
            
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            
        } catch (Exception e) {
            logger.error("处理WebSocket消息时出错", e);
            sendErrorMessage(session, "消息处理失败: " + e.getMessage());
        }
    }
    
    /**
     * 新的WebSocket连接建立
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 从URI路径中获取用户ID
        Integer userId = getUserIdFromPath(session);
        if (userId == null) {
            logger.error("无法从路径中获取用户ID，关闭连接");
            session.close(CloseStatus.BAD_DATA.withReason("未提供有效的用户ID"));
            return;
        }
        
        // 将用户会话存储起来
        userSessions.put(userId, session);
        logger.info("用户(ID:{})的通知WebSocket连接已建立", userId);
        
        // 更新通知服务中的用户会话信息
        setNotificationServiceSessions();
        
        // 发送连接成功消息
        sendConnectionSuccessMessage(session);
    }
    
    /**
     * WebSocket连接关闭
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Integer userId = getUserIdFromPath(session);
        if (userId != null) {
            userSessions.remove(userId);
            logger.info("用户(ID:{})的通知WebSocket连接已关闭，原因: {}", userId, status.getReason());
            
            // 更新通知服务中的用户会话信息
            setNotificationServiceSessions();
        }
    }
    
    /**
     * 从URI路径中获取用户ID
     * 例如: /ws/notifications/123 -> 123
     */
    private Integer getUserIdFromPath(WebSocketSession session) {
        try {
            String path = session.getUri().getPath();
            String[] segments = path.split("/");
            String userIdStr = segments[segments.length - 1];
            return Integer.parseInt(userIdStr);
        } catch (Exception e) {
            logger.error("从URI路径解析用户ID失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从查询参数中获取用户ID
     */
    private Integer getUserIdFromSession(WebSocketSession session) {
        try {
            // 首先尝试从URI路径获取
            Integer userId = getUserIdFromPath(session);
            if (userId != null) {
                return userId;
            }
            
            // 如果路径中没有，尝试从查询参数获取
            String query = session.getUri().getQuery();
            if (query != null && query.contains("userId=")) {
                String userIdStr = query.split("userId=")[1].split("&")[0];
                return Integer.parseInt(userIdStr);
            }
        } catch (Exception e) {
            logger.error("解析用户ID失败: {}", e.getMessage());
        }
        return null;
    }
    
    /**
     * 发送连接成功消息
     */
    private void sendConnectionSuccessMessage(WebSocketSession session) {
        try {
            Map<String, Object> message = new HashMap<>();
            message.put("type", "SYSTEM");
            message.put("message", "通知连接已建立");
            message.put("timestamp", System.currentTimeMillis());
            
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(message)));
            logger.debug("已发送连接成功消息");
        } catch (IOException e) {
            logger.error("发送连接成功消息失败: {}", e.getMessage());
        }
    }
    
    /**
     * 发送错误消息
     */
    private void sendErrorMessage(WebSocketSession session, String errorMsg) {
        try {
            if (session.isOpen()) {
                Map<String, Object> error = new HashMap<>();
                error.put("type", "ERROR");
                error.put("message", errorMsg);
                error.put("timestamp", System.currentTimeMillis());
                
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(error)));
                logger.debug("已发送错误消息: {}", errorMsg);
            }
        } catch (IOException e) {
            logger.error("发送错误消息失败: {}", e.getMessage());
        }
    }
    
    /**
     * 主动向用户发送通知
     * 
     * @param userId 用户ID
     * @param notificationType 通知类型
     * @param content 通知内容
     * @return 是否发送成功
     */
    public boolean sendNotification(Integer userId, String notificationType, String content) {
        WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                Map<String, Object> notification = new HashMap<>();
                notification.put("type", "NOTIFICATION");
                notification.put("notificationType", notificationType);
                notification.put("content", content);
                notification.put("timestamp", System.currentTimeMillis());
                
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(notification)));
                logger.info("已向用户(ID:{})发送类型为[{}]的通知", userId, notificationType);
                return true;
            } catch (IOException e) {
                logger.error("向用户(ID:{})发送通知失败: {}", userId, e.getMessage());
            }
        } else {
            logger.info("用户(ID:{})不在线或WebSocket会话未建立，无法发送通知", userId);
        }
        return false;
    }
} 